package com.budwk.app.miniapp.services.impl;

import cn.dev33.satoken.context.SaHolder;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.budwk.app.miniapp.common.CacheConstants;
import com.budwk.app.miniapp.common.CacheNames;
import com.budwk.app.miniapp.models.dto.SysDictDataQueryDTO;
import com.budwk.app.miniapp.models.DictDataWithSubLists;
import com.budwk.app.miniapp.services.DictService;
import com.budwk.starter.common.constant.RedisConstant;
import com.budwk.starter.common.page.PageUtil;
import com.budwk.starter.database.service.BaseServiceImpl;
import com.budwk.app.miniapp.models.SysDictData;
import com.budwk.app.miniapp.services.SysdictdataService;
import com.google.common.collect.Lists;
import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.plugins.wkcache.annotation.CacheDefaults;
import org.nutz.plugins.wkcache.annotation.CacheResult;

import java.util.*;
import java.util.stream.Collectors;

@IocBean(args = {"refer:dao"})
@CacheDefaults(cacheName =  CacheNames.SYS_DICT, isHash = false, cacheLiveTime = RedisConstant.WKCACHE_TIMEOUT)
@Slf4j
public class SysdictdataServiceImpl extends BaseServiceImpl<SysDictData> implements SysdictdataService, DictService {
    public SysdictdataServiceImpl(Dao dao) {
        super(dao);
    }

    @Inject
    private SysdictdataService sysdictdataService;

    /*
     * 获取帮助类型
     * */
    @Override
    public List<DictDataWithSubLists> dictListWithSub(SysDictData sysDictData) {
        Cnd cnd = Cnd.NEW();
        if (sysDictData.getDictLabel() != null && Strings.isNotBlank(sysDictData.getDictLabel().toString())) {
            cnd.and("dict_label", "=", sysDictData.getDictLabel());
        }
        if (sysDictData.getDictValue() != null && Strings.isNotBlank(sysDictData.getDictValue().toString())) {
            cnd.and("dict_value", "=", sysDictData.getDictValue());
        }
        if (sysDictData.getDictType() != null && Strings.isNotBlank(sysDictData.getDictType().toString())) {
            cnd.and("dict_type", "=", sysDictData.getDictType());
        }
        if (sysDictData.getStatus() != null && Strings.isNotBlank(sysDictData.getStatus().toString())) {
            cnd.and("status", "=", sysDictData.getStatus());
        }
        if (sysDictData.getDictCode() != null && Strings.isNotBlank(sysDictData.getDictCode().toString())) {
            cnd.and("dict_code", "=", sysDictData.getDictCode());
        }
        cnd.orderBy("dict_sort", PageUtil.getOrder("asc"));

        List<SysDictData> list = query(cnd);
        List<DictDataWithSubLists> resultList = Lists.newArrayList();
        for (SysDictData dictData : list) {
            DictDataWithSubLists dictDataWithSubLists = new DictDataWithSubLists();
            BeanUtil.copyProperties(dictData, dictDataWithSubLists);

            Cnd cndSub = Cnd.NEW();
            cndSub.and("parent_code", "=", dictData.getDictCode());
            cndSub.orderBy("dict_sort", "asc");
            List<SysDictData> subList = sysdictdataService.query(cndSub);

            dictDataWithSubLists.setSubList(subList);
            resultList.add(dictDataWithSubLists);
        }
        return resultList;
    }

    @Override
    public String getDictLabel(String dictType, String dictValue, String separator) {
        // 优先从本地缓存获取
        List<SysDictData> datas = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
        if (ObjectUtil.isNull(datas)) {
            datas =  this.query(Cnd.where(SysDictData::getDictType,"=",dictType).and(SysDictData::getStatus,"=",0));
            SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
        }
        Map<String, String> map = datas.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        if (StringUtils.containsAny(dictValue, separator)) {
            return Arrays.stream(dictValue.split(separator))
                    .map(v -> map.getOrDefault(v, StringUtils.EMPTY))
                    .collect(Collectors.joining(separator));
        } else {
            return map.getOrDefault(dictValue, StringUtils.EMPTY);
        }
    }

    @Override
    public String getDictValue(String dictType, String dictLabel, String separator) {
        return null;
    }

    @Override
    public List<SysDictData> getSysDictDataList(SysDictDataQueryDTO queryDTO) {
        String dictType = queryDTO.getDictType();
        if(StringUtils.isBlank(dictType)) {
            return new ArrayList<>();
        }

        List<SysDictData> dataList = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
        if (ObjectUtil.isNull(dataList)) {
            //dataList = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
            dataList = this.selectDictDataByType(dictType);
            SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, dataList);
        }

        Long parentCode = queryDTO.getParentCode();
        if(parentCode != null){
            dataList =  dataList.stream().filter(item -> Objects.equals(item.getParentCode(), parentCode)).collect(Collectors.toList());
        }

        return dataList;
    }

    /**
     * 根据字典类型查询字典数据
     *
     * @param dictType 字典类型
     * @return 字典数据集合信息
     */
    //@Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType")

    @Override
    @CacheResult(cacheKey = "${dictType}_selectDictDataByType")
    public List<SysDictData> selectDictDataByType(String dictType) {
        Cnd cnd = Cnd.NEW();
        cnd.and("dict_type", "=", dictType);
        cnd.asc(SysDictData::getDictSort);
        List<SysDictData> dictDatas = this.query(cnd);
        if (CollUtil.isNotEmpty(dictDatas)) {
            List<Long> distCodeList=dictDatas.stream().map(SysDictData::getDictCode).collect(Collectors.toList());
            List<SysDictData> childs = this.query(Cnd.where(SysDictData::getParentCode,"in",distCodeList));
            Map<Long,List<SysDictData>> childsGroup = childs.stream().collect(Collectors.groupingBy(SysDictData::getParentCode));
            dictDatas.forEach(s->{
                List<SysDictData> getChilds=childsGroup.get(s.getDictCode());
                if(CollUtil.isNotEmpty(getChilds)){
                    s.setSubList(getChilds);
                }
            });
            return dictDatas;
        }
        return null;
    }
}
